package com.ymm.lulutong.domain.impl;

import com.ymm.lulutong.constant.ProfileCodeEnum;
import com.ymm.lulutong.constant.ResultCodeEnum;
import com.ymm.lulutong.constant.WalletCodeEnum;
import com.ymm.lulutong.constants.MessgeStatusEnum;
import com.ymm.lulutong.constants.OpsPersonTypeEnum;
import com.ymm.lulutong.constants.WalletOpsEnum;
import com.ymm.lulutong.domain.ShipperCargoDomainService;
import com.ymm.lulutong.domain.ShipperWalletDomainService;
import com.ymm.lulutong.entity.Shipper;
import com.ymm.lulutong.entity.Wallet;
import com.ymm.lulutong.entity.WalletOpsLog;
import com.ymm.lulutong.mapper.ShipperProfileMapper;
import com.ymm.lulutong.mapper.ShipperWalletMapper;
import com.ymm.lulutong.mapper.ShipperWalletOpsLogMapper;
import com.ymm.lulutong.repo.SystemShipperCargoServiceRepo;
import com.ymm.lulutong.utils.Result;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.Date;
import java.util.List;
import java.util.Objects;

@Slf4j
@Service("shipperWalletDomainServiceImpl")
public class ShipperWalletDomainServiceImpl implements ShipperWalletDomainService {
    @Resource
    private ShipperWalletMapper shipperWalletMapper;

    @Resource
    private ShipperProfileMapper shipperProfileMapper;

    @Resource
    private ShipperWalletOpsLogMapper shipperWalletOpsLogMapper;

    @Resource
    private SystemShipperCargoServiceRepo systemShipperCargoServiceRepo;

    @Override
    public Result<Wallet> getWalletByShipperId(Long shipperId) {
        if (shipperId == null) {
            log.info("参数错误");
            return Result.fail(null, ResultCodeEnum.PARAMETER_NULL_ERROR.getCode(), ResultCodeEnum.PARAMETER_NULL_ERROR.getMessage());
        }
        Wallet wallet;
        try {
            Shipper shipper = shipperProfileMapper.selectById(shipperId);
            if (shipper == null) {
                log.info("不存在的用户" + shipperId);
                return Result.fail(null, ProfileCodeEnum.SHIPPER_NOT_EXIST.getCode(), ProfileCodeEnum.SHIPPER_NOT_EXIST.getMessage());
            }
            if (!shipper.getValid()) {
                log.info("账号已被注销");
                return Result.fail(null, ProfileCodeEnum.ACCOUNT_CANCELLED.getCode(), ProfileCodeEnum.ACCOUNT_CANCELLED.getMessage());
            }
            wallet = shipperWalletMapper.getWalletByShipperId(shipperId);
        } catch (Exception e) {
            e.printStackTrace();
            log.info("数据库操作错误");
            return Result.fail(null, ResultCodeEnum.DATABASE_ERROR.getCode(), ResultCodeEnum.DATABASE_ERROR.getMessage());
        }
        log.info("获取钱包成功，余额为" + wallet.getTotalBalance());
        return Result.success(wallet);
    }

    /**
     * 充值
     *
     * @param shipperId  货主Id
     * @param topUpMoney 充值金额
     * @return 日志Id
     */
    @Override
    @Transactional
    public Result<Long> topUp(Long shipperId, Integer topUpMoney) throws Exception {
        if (Objects.isNull(shipperId) || Objects.isNull(topUpMoney) || topUpMoney < 0) {
            log.info("参数错误");
            return Result.fail(null, ResultCodeEnum.PARAMETER_NULL_ERROR.getCode(), ResultCodeEnum.PARAMETER_NULL_ERROR.getMessage());
        }
        Shipper shipper;
        shipper = shipperProfileMapper.selectById(shipperId);
        if (shipper == null) {
            log.info("不存在的用户" + shipperId);
            return Result.fail(null, ProfileCodeEnum.SHIPPER_NOT_EXIST.getCode(), ProfileCodeEnum.SHIPPER_NOT_EXIST.getMessage());
        }
        if (Boolean.FALSE.equals(shipper.getValid())) {
            log.info("账号已被注销");
            return Result.fail(null, ProfileCodeEnum.ACCOUNT_CANCELLED.getCode(), ProfileCodeEnum.ACCOUNT_CANCELLED.getMessage());
        }

        Integer newBalance = shipper.getTotalBalance() + topUpMoney;
        WalletOpsLog walletOpsLog = new WalletOpsLog();
        walletOpsLog.setShipperId(shipperId);
        walletOpsLog.setOpsType(WalletOpsEnum.TOP_UP.getCode());
        walletOpsLog.setMoney(topUpMoney);
        walletOpsLog.setOpsPersonType(OpsPersonTypeEnum.SHIPPER.getCode());
        walletOpsLog.setOpsPersonId(shipperId);
        walletOpsLog.setCreateTime(new Date());
        walletOpsLog.setUpdateTime(new Date());
        walletOpsLog.setExecutionStatus(MessgeStatusEnum.IN_EXECUTION.getCode());
        shipperWalletOpsLogMapper.add(walletOpsLog);
        shipperWalletMapper.updateTotalBalanceByShipperId(shipperId, newBalance);
        shipper.setTotalBalance(newBalance);
        shipperWalletOpsLogMapper.updateExecutionStatusByLogId(walletOpsLog.getLogId(), MessgeStatusEnum.COMPLETED.getCode());
        log.info("充值成功，余额为" + shipper.getTotalBalance());
        return Result.success(walletOpsLog.getLogId());
    }

    /**
     * 返现
     *
     * @param shipperId     货主Id
     * @param cashBackMoney 返现金额
     * @param cargoId       关联的货源Id，可以为空
     * @param orderId       关联的订单Id，可以为空
     * @return 日志Id
     */
    @Override
    @Transactional
    public Result<Long> cashBack(Long shipperId, Integer cashBackMoney, Long cargoId, Long orderId) throws Exception {
        if (Objects.isNull(shipperId) || Objects.isNull(cashBackMoney) || cashBackMoney < 0) {
            log.info("参数错误");
            return Result.fail(null, ResultCodeEnum.PARAMETER_NULL_ERROR.getCode(), ResultCodeEnum.PARAMETER_NULL_ERROR.getMessage());
        }
        Shipper shipper;
        shipper = shipperProfileMapper.selectById(shipperId);
        if (shipper == null) {
            log.info("不存在的用户" + shipperId);
            return Result.fail(null, ProfileCodeEnum.SHIPPER_NOT_EXIST.getCode(), ProfileCodeEnum.SHIPPER_NOT_EXIST.getMessage());
        }
        if (Boolean.FALSE.equals(shipper.getValid())) {
            log.info("账号已被注销");
            return Result.fail(null, ProfileCodeEnum.ACCOUNT_CANCELLED.getCode(), ProfileCodeEnum.ACCOUNT_CANCELLED.getMessage());
        }

        Integer newBalance = shipper.getTotalBalance() + cashBackMoney;
        WalletOpsLog walletOpsLog = new WalletOpsLog();
        walletOpsLog.setShipperId(shipperId);
        walletOpsLog.setCargoId(cargoId);
        walletOpsLog.setOrderId(orderId);
        walletOpsLog.setOpsType(WalletOpsEnum.CASH_BACK.getCode());
        walletOpsLog.setMoney(cashBackMoney);
        walletOpsLog.setOpsPersonType(OpsPersonTypeEnum.SYSTEM.getCode());
        walletOpsLog.setOpsPersonId(null);
        walletOpsLog.setCreateTime(new Date());
        walletOpsLog.setUpdateTime(new Date());
        walletOpsLog.setExecutionStatus(MessgeStatusEnum.IN_EXECUTION.getCode());
        shipperWalletOpsLogMapper.add(walletOpsLog);
        shipperWalletMapper.updateTotalBalanceByShipperId(shipperId, newBalance);
        shipper.setTotalBalance(newBalance);
        shipperWalletOpsLogMapper.updateExecutionStatusByLogId(walletOpsLog.getLogId(), MessgeStatusEnum.COMPLETED.getCode());
        log.info("返现成功，余额为" + shipper.getTotalBalance());
        return Result.success(walletOpsLog.getLogId());
    }

    /**
     * 退款
     *
     * @param shipperId   货主Id
     * @param refundMoney 退款金额
     * @param cargoId     关联的货源Id，可以为空
     * @return 日志Id
     */
    @Override
    @Transactional
    public Result<Long> refund(Long shipperId, Integer refundMoney, Long cargoId, Long orderId) throws Exception {
        if (Objects.isNull(shipperId) || Objects.isNull(refundMoney) || refundMoney < 0) {
            log.info("参数错误");
            return Result.fail(null, ResultCodeEnum.PARAMETER_NULL_ERROR.getCode(), ResultCodeEnum.PARAMETER_NULL_ERROR.getMessage());
        }
        Shipper shipper;
        shipper = shipperProfileMapper.selectById(shipperId);
        if (shipper == null) {
            log.info("不存在的用户" + shipperId);
            return Result.fail(null, ProfileCodeEnum.SHIPPER_NOT_EXIST.getCode(), ProfileCodeEnum.SHIPPER_NOT_EXIST.getMessage());
        }
        if (Boolean.FALSE.equals(shipper.getValid())) {
            log.info("账号已被注销");
            return Result.fail(null, ProfileCodeEnum.ACCOUNT_CANCELLED.getCode(), ProfileCodeEnum.ACCOUNT_CANCELLED.getMessage());
        }

        Integer newBalance = shipper.getTotalBalance() + refundMoney;
        WalletOpsLog walletOpsLog = new WalletOpsLog();
        walletOpsLog.setShipperId(shipperId);
        walletOpsLog.setCargoId(cargoId);
        walletOpsLog.setOrderId(orderId);
        walletOpsLog.setOpsType(WalletOpsEnum.REFUND.getCode());
        walletOpsLog.setMoney(refundMoney);
        walletOpsLog.setOpsPersonType(OpsPersonTypeEnum.SYSTEM.getCode());
        walletOpsLog.setOpsPersonId(null);
        walletOpsLog.setCreateTime(new Date());
        walletOpsLog.setUpdateTime(new Date());
        walletOpsLog.setExecutionStatus(MessgeStatusEnum.IN_EXECUTION.getCode());
        shipperWalletOpsLogMapper.add(walletOpsLog);
        shipperWalletMapper.updateTotalBalanceByShipperId(shipperId, newBalance);
        shipper.setTotalBalance(newBalance);
        shipperWalletOpsLogMapper.updateExecutionStatusByLogId(walletOpsLog.getLogId(), MessgeStatusEnum.COMPLETED.getCode());
        log.info("退款成功，余额为" + shipper.getTotalBalance());
        return Result.success(walletOpsLog.getLogId());
    }

    /**
     * 支付
     *
     * @param shipperId 货主Id
     * @param payMoney  支付金额
     * @return 日志Id
     */
    @Override
    @Transactional
    public Result<Long> pay(Long shipperId, Integer payMoney) throws Exception {
        if (Objects.isNull(shipperId) || Objects.isNull(payMoney) || payMoney < 0) {
            log.info("参数错误");
            return Result.fail(null, ResultCodeEnum.PARAMETER_NULL_ERROR.getCode(), ResultCodeEnum.PARAMETER_NULL_ERROR.getMessage());
        }
        Shipper shipper;
        shipper = shipperProfileMapper.selectById(shipperId);
        if (shipper == null) {
            log.info("不存在的用户" + shipperId);
            return Result.fail(null, ProfileCodeEnum.SHIPPER_NOT_EXIST.getCode(), ProfileCodeEnum.SHIPPER_NOT_EXIST.getMessage());
        }
        if (Boolean.FALSE.equals(shipper.getValid())) {
            log.info("账号已被注销");
            return Result.fail(null, ProfileCodeEnum.ACCOUNT_CANCELLED.getCode(), ProfileCodeEnum.ACCOUNT_CANCELLED.getMessage());
        }

        Integer newBalance = shipper.getTotalBalance() - payMoney;
        if (newBalance.compareTo(0) < 0) {
            return Result.fail(null, WalletCodeEnum.BALANCE_LACK.getCode(), WalletCodeEnum.BALANCE_LACK.getMessage());
        }
        WalletOpsLog walletOpsLog = new WalletOpsLog();
        walletOpsLog.setShipperId(shipperId);
        walletOpsLog.setOpsType(WalletOpsEnum.PAY.getCode());
        walletOpsLog.setMoney(-payMoney);
        walletOpsLog.setOpsPersonType(OpsPersonTypeEnum.SHIPPER.getCode());
        walletOpsLog.setOpsPersonId(shipperId);
        walletOpsLog.setCreateTime(new Date());
        walletOpsLog.setUpdateTime(new Date());
        walletOpsLog.setExecutionStatus(MessgeStatusEnum.IN_EXECUTION.getCode());
        shipperWalletOpsLogMapper.add(walletOpsLog);
        shipperWalletMapper.updateTotalBalanceByShipperId(shipperId, newBalance);
        shipper.setTotalBalance(newBalance);
        shipperWalletOpsLogMapper.updateExecutionStatusByLogId(walletOpsLog.getLogId(), MessgeStatusEnum.COMPLETED.getCode());

        log.info("支付成功，余额为" + shipper.getTotalBalance());
        return Result.success(walletOpsLog.getLogId());
    }

    /**
     * 为发货付款
     *
     * @param shipperId 货主Id
     * @param payMoney  付款金额
     * @param cargoId   货源Id
     * @return 日志Id
     */
    @Override
    @Transactional
    public Result<Long> payForCargo(Long shipperId, Integer payMoney, Long cargoId) throws Exception {
        if (Objects.isNull(shipperId) || Objects.isNull(payMoney) || payMoney < 0) {
            log.info("参数错误");
            return Result.fail(null, ResultCodeEnum.PARAMETER_NULL_ERROR.getCode(), ResultCodeEnum.PARAMETER_NULL_ERROR.getMessage());
        }
        Shipper shipper;
        shipper = shipperProfileMapper.selectById(shipperId);
        if (shipper == null) {
            log.info("不存在的用户" + shipperId);
            return Result.fail(null, ProfileCodeEnum.SHIPPER_NOT_EXIST.getCode(), ProfileCodeEnum.SHIPPER_NOT_EXIST.getMessage());
        }
        if (Boolean.FALSE.equals(shipper.getValid())) {
            log.info("账号已被注销");
            return Result.fail(null, ProfileCodeEnum.ACCOUNT_CANCELLED.getCode(), ProfileCodeEnum.ACCOUNT_CANCELLED.getMessage());
        }

        Integer newBalance = shipper.getTotalBalance() - payMoney;
        if (newBalance.compareTo(0) < 0) {
            return Result.fail(null, WalletCodeEnum.BALANCE_LACK.getCode(), WalletCodeEnum.BALANCE_LACK.getMessage());
        }
        WalletOpsLog walletOpsLog = new WalletOpsLog();
        walletOpsLog.setShipperId(shipperId);
        walletOpsLog.setOpsType(WalletOpsEnum.PAY.getCode());
        walletOpsLog.setCargoId(cargoId);
        walletOpsLog.setMoney(-payMoney);
        walletOpsLog.setOpsPersonType(OpsPersonTypeEnum.SHIPPER.getCode());
        walletOpsLog.setOpsPersonId(shipperId);
        walletOpsLog.setCreateTime(new Date());
        walletOpsLog.setUpdateTime(new Date());
        walletOpsLog.setExecutionStatus(MessgeStatusEnum.IN_EXECUTION.getCode());
        shipperWalletOpsLogMapper.add(walletOpsLog);
        shipperWalletMapper.updateTotalBalanceByShipperId(shipperId, newBalance);
        shipper.setTotalBalance(newBalance);
        shipperWalletOpsLogMapper.updateExecutionStatusByLogId(walletOpsLog.getLogId(), MessgeStatusEnum.COMPLETED.getCode());

        systemShipperCargoServiceRepo.payForCargoSuccess(shipperId, cargoId);
        log.info("支付成功，余额为" + shipper.getTotalBalance());
        return Result.success(walletOpsLog.getLogId());
    }

    /**
     * 提现
     *
     * @param shipperId       货主Id
     * @param withdrawalMoney 提现金额
     * @return 日志Id
     */
    @Override
    @Transactional
    public Result<Long> withdrawal(Long shipperId, Integer withdrawalMoney) throws Exception {
        if (Objects.isNull(shipperId) || Objects.isNull(withdrawalMoney) || withdrawalMoney < 0) {
            log.info("参数错误");
            return Result.fail(null, ResultCodeEnum.PARAMETER_NULL_ERROR.getCode(), ResultCodeEnum.PARAMETER_NULL_ERROR.getMessage());
        }
        Shipper shipper;
        shipper = shipperProfileMapper.selectById(shipperId);
        if (shipper == null) {
            log.info("不存在的用户");
            return Result.fail(null, ProfileCodeEnum.SHIPPER_NOT_EXIST.getCode(), ProfileCodeEnum.SHIPPER_NOT_EXIST.getMessage());
        }
        if (Boolean.FALSE.equals(shipper.getValid())) {
            log.info("账号已被注销");
            return Result.fail(null, ProfileCodeEnum.ACCOUNT_CANCELLED.getCode(), ProfileCodeEnum.ACCOUNT_CANCELLED.getMessage());
        }

        Integer newBalance = shipper.getTotalBalance() - withdrawalMoney;
        if (newBalance.compareTo(0) < 0) {
            return Result.fail(null, WalletCodeEnum.BALANCE_LACK.getCode(), WalletCodeEnum.BALANCE_LACK.getMessage());
        }
        WalletOpsLog walletOpsLog = new WalletOpsLog();
        walletOpsLog.setShipperId(shipperId);
        walletOpsLog.setOpsType(WalletOpsEnum.WITHDRAWAL.getCode());
        walletOpsLog.setMoney(-withdrawalMoney);
        walletOpsLog.setOpsPersonType(OpsPersonTypeEnum.SHIPPER.getCode());
        walletOpsLog.setOpsPersonId(shipperId);
        walletOpsLog.setCreateTime(new Date());
        walletOpsLog.setUpdateTime(new Date());
        walletOpsLog.setExecutionStatus(MessgeStatusEnum.IN_EXECUTION.getCode());
        shipperWalletOpsLogMapper.add(walletOpsLog);
        shipperWalletMapper.updateTotalBalanceByShipperId(shipperId, newBalance);
        shipper.setTotalBalance(newBalance);
        shipperWalletOpsLogMapper.updateExecutionStatusByLogId(walletOpsLog.getLogId(), MessgeStatusEnum.COMPLETED.getCode());
        log.info("提现成功，余额为" + shipper.getTotalBalance());
        return Result.success(walletOpsLog.getLogId());
    }


    /**
     * 获取账单流水
     *
     * @param shipperId 货主Id
     * @return 全部账单
     */
    @Override
    public Result<List<WalletOpsLog>> getRunningAccountByShipperId(Long shipperId) {
        if (Objects.isNull(shipperId)) {
            return Result.fail(null, ResultCodeEnum.PARAMETER_NULL_ERROR.getCode(), ResultCodeEnum.PARAMETER_NULL_ERROR.getMessage());
        }
        List<WalletOpsLog> walletOpsLogs = shipperWalletOpsLogMapper.listByShipperId(shipperId);
        if (Objects.isNull(walletOpsLogs)) {
            return Result.fail(null, ResultCodeEnum.FAIL);
        }
        return Result.success(walletOpsLogs);
    }

    /**
     * 根据条件更新一条记录
     *
     * @param condition 更新条件
     * @return 日志Id
     */
    @Override
    public Result<Long> updateLogByLogIdOnCondition(WalletOpsLog condition) throws Exception {
        if (Objects.isNull(condition) || Objects.isNull(condition.getLogId())) {
            return Result.fail(null, ResultCodeEnum.PARAMETER_NULL_ERROR.getCode(), ResultCodeEnum.PARAMETER_NULL_ERROR.getMessage());
        }
        boolean flag = shipperWalletOpsLogMapper.updateByLogIdOnCondition(condition);
        if (flag) {
            return Result.success(condition.getLogId());
        } else {
            return Result.fail(null, ResultCodeEnum.FAIL);
        }
    }
}
